<!DOCTYPE html>
            <html lang="en" data-theme="light">

                <head>
                    <meta charset="utf-8">

                    <title>The Book of Shaders</title>
                    <link href="/favicon.gif" rel="shortcut icon" />
                    <meta name="keywords" content="shader,openGL,WebGL,GLSL,book,procedural,generative" />
                    <meta name="description" content="Gentle step-by-step guide through the abstract and complex universe of Fragment Shaders." />

                    <!— Open Graph data —>
                    <meta property="og:type" content="article" />
                    <meta property="og:title" content="The Book of Shaders" />
                    <meta property="og:site_name" content="The Book of Shaders" />
                    <meta property="og:description" content="Gentle step-by-step guide through the abstract and complex universe of Fragment Shaders." />
                    <meta property="og:image" content="http://thebookofshaders.com/thumb.png" />
                    <meta property="og:image:secure_url" content="https://thebookofshaders.com/thumb.png" />
                    <meta property="og:image:type" content="image/png" />
                    <meta property="og:image:width" content="500" />
                    <meta property="og:image:height" content="500" />

                    <link href="/favicon.gif" rel="shortcut icon" />

                    <!-- Highlight -->
                    <link type="text/css" rel="stylesheet" href="/css/github.css">
                    <script type="text/javascript" src="/src/highlight.min.js"></script>
                    <!-- GlslCanvas -->
                    <script type="text/javascript" src="/src/glslCanvas/GlslCanvas.js"></script>

                    <!-- GlslEditor -->
                    <link type="text/css" rel="stylesheet" href="/src/glslEditor/glslEditor.css">
                    <script type="application/javascript" src="/src/glslEditor/glslEditor.js"></script>

                    <!-- GlslGallery -->
                    <link type="text/css" rel="stylesheet" href="/src/glslGallery/glslGallery.css">
                    <script type="application/javascript" src="/src/glslGallery/glslGallery.js"></script>

                    <!-- Main style -->
                    <link type="text/css" rel="stylesheet" href="/css/styles.css">

                </head>

                <body>
                    <div class="toc-header">
                        <p class="subtitle"><a href="https://thebookofshaders.com/">The Book of Shaders</a> by <a href="http://patriciogonzalezvivo.com">Patricio Gonzalez Vivo</a> & <a href="http://jenlowe.net">Jen Lowe</a> </p>
                        <p>  <a href=".">中文版</a> - <a href="https://thebookofshaders.com/">English</a></p>
                    </div>
                    <hr>

                    <div id="content"><p><canvas id="custom" class="canvas" data-fragment-url="examples/moon.frag" data-textures="examples/images/moon-texture.jpg" width="350px" height="350px"></canvas></p>
<h1 id="the-book-of-shaders">The Book of Shaders</h1>
<p><em>by <a href="http://patriciogonzalezvivo.com/">Patricio Gonzalez Vivo</a></em></p>
<p>这是一本关于 Fragment Shaders（片段着色器）的入门指南，它将一步一步地带你领略其中的纷繁与抽象。</p>
<div class="header">
<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=B5FSVSHGEATCG" style="float: right;"><img src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif" alt=""></a>
</div>

<h2 id="关于翻译">关于翻译</h2>
<p>这本书是 Patricio 的 the Book of Shaders 的中文翻译。我们希望借此将 Shader 这个有趣有益的工具介绍给更多国人。能力所限，不免有误，如有翻译不当，也请多多指出。</p>
<p>感谢 Patricio 对我们的翻译的信任和支持。</p>
<h2 id="目录">目录</h2>
<ul>
<li><p><a href="00/?lan=ch">关于这本书</a></p>
</li>
<li><p>开始</p>
<ul>
<li><a href="01/?lan=ch">什么是片段着色器（Fragment Shader）？</a></li>
<li><a href="02/?lan=ch">“Hello world!”</a></li>
<li><a href="03/?lan=ch">Uniforms值</a></li>
<li><a href="04/?lan=ch">运行你的 shader</a></li>
</ul>
</li>
<li><p>用算法绘画</p>
<ul>
<li><a href="05/?lan=ch">造型函数</a></li>
<li><a href="06/?lan=ch">颜色</a></li>
<li><a href="07/?lan=ch">形状</a></li>
<li><a href="08/?lan=ch">矩阵</a></li>
<li><a href="09/?lan=ch">图案</a></li>
</ul>
</li>
<li><p>生成设计</p>
<ul>
<li><a href="10/?lan=ch">随机</a></li>
<li><a href="11/?lan=ch">噪声</a></li>
<li><a href="12/?lan=ch">网格噪声</a></li>
<li><a href="13/?lan=ch">分形布朗运动</a></li>
<li>分形</li>
</ul>
</li>
<li><p>图像处理:</p>
<ul>
<li>纹理</li>
<li>图像处理</li>
<li>卷积核</li>
<li>滤镜</li>
<li>其他效果</li>
</ul>
</li>
<li><p>模拟</p>
<ul>
<li>乒乓</li>
<li>Conway生命游戏</li>
<li>水波</li>
<li>水彩</li>
<li>反应扩散</li>
</ul>
</li>
<li><p>3D 图形</p>
<ul>
<li>灯光</li>
<li>法线贴图</li>
<li>凹凸贴图</li>
<li>光线跟踪（Ray marching）</li>
<li>环境贴图 (spherical and cube)</li>
<li>折射和反射</li>
</ul>
</li>
<li><p><a href="appendix/">附录:</a> 其他阅读本书的方式</p>
<ul>
<li><a href="appendix/?lan=ch">如何离线阅读此书?</a></li>
<li><a href="appendix/?lan=ch">如何在树莓派上运行示例程序?</a></li>
<li><a href="appendix/?lan=ch">如何打印这本书</a></li>
</ul>
</li>
<li><p><a href="examples/?lan=ch">example gallery</a></p>
</li>
<li><p><a href="glossary/?lan=ch">词汇表</a></p>
</li>
</ul>
<h2 id="关于作者">关于作者</h2>
<p><a href="http://patriciogonzalezvivo.com/">Patricio Gonzalez Vivo</a> (1982, 布宜诺斯艾利斯, 阿根廷) 是一个驻地纽约的艺术家、开发者。他致力于探索有机和人造、模拟信号和数字信号、个体和整体之间的空间。他用代码这种富有表达力的语言来创造更美好的事物。</p>
<p>Patricio 研习和实践精神疗法（psychotherapy）和表达性艺术治疗（expressive art therapy）。他毕业于 Parsons 的设计与科技专业，且目前执教于此。目前他作为 Mapzen 的图形开发工程师制作一些开源的 mapping tool。</p>
<div class="header"><a href="https://twitter.com/patriciogv" target="_blank">Twitter</a> - <a href="https://github.com/patriciogonzalezvivo" target="_blank">GitHub</a> - <a href="https://vimeo.com/patriciogv" target="_blank">Vimeo</a> - <a href="https://www.flickr.com/photos/106950246@N06/" target="_blank"> Flickr</a></div>

<h2 id="关于译者">关于译者</h2>
<ul>
<li><p><a href="https://github.com/tornoteli">tornote</a> 翻译 00-05 及第 11 章。</p>
</li>
<li><p><a href="https://github.com/Artrustee">Artrustee</a> 翻译 06-10 章。</p>
</li>
</ul>
<p>后续章节作者仍在撰写中，如果感兴趣可以在 github 上查看部分后续章节代码。</p>
<h2 id="致谢">致谢</h2>
<p>感谢我的妻子 <a href="http://www.datatelling.com/">Jen Lowe</a>, 感谢她无条件的支持、帮助以及编辑此书。</p>
<p>感谢 <a href="http://alignedleft.com/">Scott Murray</a> 给予的启发和建议。</p>
<p>感谢 <a href="https://twitter.com/kyndinfo">Kenichi Yoneda (Kynd)</a> 和 <a href="https://twitter.com/sawakohome">Sawako</a> 的 <a href="?lan=jp">日文版翻译(日本語訳)</a></p>
<p>感谢 <a href="https://www.facebook.com/tong.lee.9484">Tong Li</a> 和 <a href="https://www.facebook.com/archer.zetta?pnref=story">Yi Zhang</a> 的 <a href="?lan=ch">中文版(Chinese)</a> 翻译。</p>
<p>感谢 <a href="https://www.facebook.com/fkkcloud">Jae Hyun Yoo</a> 的 <a href="?lan=kr">韩文版 (한국어)</a> 翻译。</p>
<p>感谢 Nahuel Coppero (Necsoft) 的 <a href="?lan=es">西班牙语(español)</a> 翻译。</p>
<p>感谢 <a href="http://karim.naaji.fr/">Karim Naaji</a> 在代码和想法上的支持和贡献。</p>
<p>感谢所有相信这个项目的人<a href="https://github.com/patriciogonzalezvivo/thebookofshaders/graphs/contributors">contributed with fixes</a> 以及大家的捐赠.</p>
</div>

                    <hr>
                    

                    <footer>
                        <p> Copyright 2015 <a href="http://www.patriciogonzalezvivo.com" target="_blank">Patricio Gonzalez Vivo</a> </p>
                    </footer>

                    <script src="/src/three.min.js"></script>

                    <script id="vertexShader" type="x-shader/x-vertex">
                        void main() {
                            gl_Position = vec4( position, 1.0 );
                        }
                    </script>

                    <script id="fragmentShader" type="x-shader/x-fragment">
                        uniform vec2 u_resolution;
                        uniform vec2 u_mouse;
                        uniform float u_time;

                        void main() {
                            vec2 st = gl_FragCoord.xy/u_resolution.xy;
                            gl_FragColor=vec4(st.x,st.y,0.0,1.0);
                        }
                    </script>

                    <script>
                        var camera, scene, renderer, clock;
                        var uniforms;
                        var mouse = { x: 0, y: 0 };

                        document.onmousemove = getMouseXY;

                        function getMouseXY (e) {
                            mouse.x = e.pageX;
                            mouse.y = e.pageY;
                        }

                        function init () {

                            camera = new THREE.Camera();
                            camera.position.z = 1;

                            scene = new THREE.Scene();
                            clock = new THREE.Clock();

                            var geometry = new THREE.PlaneBufferGeometry(2, 2);

                            uniforms = {
                                u_time: { type: "f", value: 1.0 },
                                u_mouse: { type: "v2", value: new THREE.Vector2() },
                                u_resolution: { type: "v2", value: new THREE.Vector2() }
                            };

                            var material = new THREE.ShaderMaterial({
                                uniforms: uniforms,
                                vertexShader: document.getElementById('vertexShader').textContent,
                                fragmentShader: document.getElementById('fragmentShader').textContent
                            });

                            var mesh = new THREE.Mesh(geometry, material);
                            scene.add(mesh);

                            renderer = new THREE.WebGLRenderer();
                            renderer.setPixelRatio(window.devicePixelRatio);

                            container.appendChild(renderer.domElement);

                            onWindowResize();
                            window.addEventListener('resize', onWindowResize, false);
                        }

                        function onWindowResize (event) {
                            renderer.setSize(window.innerWidth, window.innerHeight);
                            uniforms.u_resolution.value.x = renderer.domElement.width;
                            uniforms.u_resolution.value.y = renderer.domElement.height;
                            uniforms.u_mouse.value.x = mouse.x;
                            uniforms.u_mouse.value.y = mouse.y;
                        }

                        function animate () {
                            requestAnimationFrame(animate);
                            render();
                        }

                        function render () {
                            uniforms.u_time.value += clock.getDelta();
                            renderer.render(scene, camera);
                        }

                        var container = document.getElementById('container');

                        if (container) {

                            init();
                            animate();
                        }
                    </script>
                    <script type="text/javascript" src="/src/main.js" defer></script>
                </body>

            </html>